package cn.tedu.xuehaoyuandemo.controller;


import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * 分布式锁
 */
@Slf4j
@RestController
@RequestMapping("Product")
public class Redisson {
    @Autowired
  private StringRedisTemplate redisTemplate;
   @Autowired
   private  Redisson redisson;
//用redis实现分布式锁
    @RequestMapping("/deduct_stock")
    public String deductStock() {
        String lockKey="lock:product:101";
        //5.为防止超卖用的是redisnx进行操作 因为nx相当于做了判定如果redis存在这个key就不会出修改或者读取，而正常的redis不行
       // Boolean xuehaoyuan = redisTemplate.opsForValue().setIfAbsent(lockKey, "xuehaoyuan");
        //6.但是我们如果这样用nx的如果线程走到中间死掉的话就不会一直过去所以亚奥设置过期时间,设置为30秒，可是现在问题当在第一行进行nx设置key的时候出现电脑死机等情况发生宕机代码
        //代码执行不到这里的话一件设置不了过期时间所以就有了第7步
       // redisTemplate.expire(lockKey,30, TimeUnit.SECONDS);
        //10.我们要设置个uuid来确保线程肯定是自己的
       // String clientId = UUID.randomUUID().toString();
        //7.直接设置redisnx的key和过期时间
        //Boolean xuehaoyuan = redisTemplate.opsForValue().setIfAbsent(lockKey, clientId, 30, TimeUnit.SECONDS);
        //9.判定下还有没有库存如果有的话就进行下一步，没有就直接返回
        //if (!xuehaoyuan){
        //    return "改商品已经没有";
        //}
        //1.先从redis取出key  取出库存
        //11.为了方便现在用分布式锁来实现
     //  !!!!!!!!!!  RLock redissonLock= redisson.getLock(lockKey);
       //!!!!!!!!!!!redissonLock.lock();
        try {
            int stock = Integer.parseInt(redisTemplate.opsForValue().get("stock"));
            //2.如果库存数>0
            if (stock > 0) {
                //3.如果库存>0进行-1操作
                int realStick = stock - 1;
                //4.然后在将减完1的库存在重新放到redis里
                redisTemplate.opsForValue().set("stock", realStick + "");
                System.out.println("扣减库存成功，剩余库存数为" + realStick);
            } else {
                System.out.println("扣减库存失败，库存不足");
            }
        }finally {
            //8.因为我们执行完这个些代码后要删除redisnx如果执行代码的中间发生了异常，程序终端怎么办？所以我们要try cath finally里去执行，且要 看看执行的这个
            //线程是不是我们自己的
           // if(clientId.equals(redisTemplate.opsForValue().get(lockKey))){
             //   redisTemplate.delete(lockKey);
            //}
        //!!!!!!!!!!! 带感叹号的都是分布式锁    redissonLock.unlock();
        }
        return null;
    }


}
